{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# Pull Portfolio Factor Risk Data with GS Quant\n",
    "\n",
    "## Authenticate and Initialize Your Session\n",
    "\n",
    "First you will import the necessary modules and add your client id and client secret."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from IPython.display import display\n",
    "\n",
    "from gs_quant.markets.portfolio_manager import PortfolioManager\n",
    "from gs_quant.markets.report import FactorRiskViewsMode, FactorRiskUnit, FactorRiskTableMode\n",
    "from gs_quant.markets.securities import SecurityMaster, AssetIdentifier\n",
    "from gs_quant.session import GsSession, Environment\n",
    "\n",
    "client = None\n",
    "secret = None\n",
    "scopes = None\n",
    "\n",
    "## External users must fill in their client ID and secret below and comment out the line below\n",
    "\n",
    "#client = 'ENTER CLIENT ID'\n",
    "#secret = 'ENTER CLIENT SECRET'\n",
    "#scopes = ('read_product_data read_financial_data run_analytics',)\n",
    "\n",
    "GsSession.use(\n",
    "    Environment.PROD,\n",
    "    client_id=client,\n",
    "    client_secret=secret,\n",
    "    scopes=scopes\n",
    ")\n",
    "\n",
    "print('GS Session initialized.')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Get Portfolio Factor Risk Report"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "risk_report = PortfolioManager('ENTER PORTFOLIO ID').get_factor_risk_report(risk_model_id='ENTER RISK MODEL ID')\n",
    "\n",
    "print(f'Factor risk report found with ID: {risk_report.id}')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "Want to query data for an active risk report? Leverage the `SecurityMaster` class to retrieve the benchmark identifier and\n",
    "pass it into the `get_factor_risk_report` function:"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "benchmark = SecurityMaster.get_asset(id_value='SPX', id_type=AssetIdentifier.BLOOMBERG_ID)\n",
    "\n",
    "risk_report = PortfolioManager('ENTER PORTFOLIO ID').get_factor_risk_report(risk_model_id='ENTER RISK MODEL ID',\n",
    "                                                                            benchmark_id=benchmark.get_marquee_id())\n",
    "\n",
    "print(f'Factor risk report found with ID: {risk_report.id}')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Current Portfolio Risk\n",
    "\n",
    "Once your risk report is scheduled as of the latest business day, you can view updated risk data broken down by factor category:"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "category_table = risk_report.get_view(\n",
    "  start_date=risk_report.latest_end_date,\n",
    "  end_date=risk_report.latest_end_date,\n",
    "  unit=FactorRiskUnit.Notional\n",
    ").get('factorCategoriesTable')\n",
    "\n",
    "category_df = pd.DataFrame(category_table).filter(items=['name', 'proportionOfRisk', 'marginalContributionToRiskPercent', 'relativeMarginalContributionToRisk', 'exposure', 'avgProportionOfRisk'])\n",
    "category_df.rename(\n",
    "  columns={\n",
    "    'proportionOfRisk': 'Prop. of Risk',\n",
    "    'marginalContributionToRiskPercent': 'MCTR Percent',\n",
    "    'relativeMarginalContributionToRisk': 'MCTR (USD)',\n",
    "    'exposure': 'Exposure (USD)',\n",
    "    'avgProportionOfRisk': 'Avg Prop. of Risk'\n",
    "  },\n",
    "  inplace=True\n",
    ")\n",
    "\n",
    "display(category_df)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "It is also possible to get a similar table for all the factors in a factor category. In this case, let's pull risk data for all the Style factors:"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "factor_table = risk_report.get_view(\n",
    "  factor_category='Style',\n",
    "  start_date=risk_report.latest_end_date,\n",
    "  end_date=risk_report.latest_end_date,\n",
    "  unit=FactorRiskUnit.Notional\n",
    ").get('factorsTable')\n",
    "\n",
    "factor_df = pd.DataFrame(factor_table).filter(items=['name', 'proportionOfRisk', 'marginalContributionToRiskPercent', 'relativeMarginalContributionToRisk', 'exposure', 'avgProportionOfRisk'])\n",
    "factor_df.rename(\n",
    "  columns={\n",
    "    'proportionOfRisk': 'Prop. of Risk',\n",
    "    'marginalContributionToRiskPercent': 'MCTR %',\n",
    "    'relativeMarginalContributionToRisk': 'MCTR (USD)',\n",
    "    'exposure': 'Exposure (USD)',\n",
    "    'avgProportionOfRisk': 'Avg Prop. of Risk'\n",
    "  },\n",
    "  inplace=True\n",
    ")\n",
    "\n",
    "display(factor_df)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "For an asset-level risk breakdown for a set of factors, leverage the get_table() function on the FactorRiskReport class. In this case, let's see the Z-Scores for the factors Beta, Dividend Yield, and Downside Risk:"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "zscore_table = risk_report.get_table(\n",
    "    mode=FactorRiskTableMode.ZScore,\n",
    "    factors=[\"Beta\",\"Dividend Yield\",\"Downside Risk\"]    # Skip passing in a value here to get a table with all model factors\n",
    ")\n",
    "\n",
    "display(pd.DataFrame(zscore_table))"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "## Historical Portfolio Risk\n",
    "\n",
    "First let's pull the daily annualized risk across the duration of your portfolio:"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "risk_data = risk_report.get_view(\n",
    "  start_date=risk_report.earliest_start_date,\n",
    "  end_date=risk_report.latest_end_date,\n",
    "  unit=FactorRiskUnit.Notional\n",
    ")\n",
    "\n",
    "historical_risk = pd.DataFrame(risk_data.get('overviewTimeSeries')).filter(items=['date', 'annualizedExAnteRiskPercent']).set_index('date')\n",
    "historical_risk.rename(columns={'annualizedExAnteRiskPercent': 'Total Risk'}, inplace=True)\n",
    "\n",
    "historical_risk.plot(title='Annualized Risk % (ex-ante)')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "For each day, you can see what percent of your risk is contributed to factor risk and what percent is idiosyncratic:"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "historical_risk = pd.DataFrame(risk_data.get('overviewTimeSeries')).filter(items=['date', 'factorProportionOfRisk', 'specificProportionOfRisk']).set_index('date')\n",
    "historical_risk.rename(columns={'factorProportionOfRisk': 'Factor Risk', 'specificProportionOfRisk': 'Specific Risk'}, inplace=True)\n",
    "\n",
    "historical_risk.plot(title='Factor and Specific Risk')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "It's even possible to break down that factor risk further by category..."
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "prop_of_risk = risk_report.get_factor_proportion_of_risk(\n",
    "  factor_names=['Market', 'Industry', 'Style'],\n",
    "  start_date=risk_report.earliest_start_date,\n",
    "  end_date=risk_report.latest_end_date\n",
    ").set_index('date')\n",
    "\n",
    "prop_of_risk.plot(title='Proportion of Risk By Factor Category')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "And by factors within a category. In this case, let's try the Style factors:"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "prop_of_risk = risk_report.get_factor_proportion_of_risk(\n",
    "  factor_categories=['Style'],\n",
    "  start_date=risk_report.earliest_start_date,\n",
    "  end_date=risk_report.latest_end_date\n",
    ").set_index('date')\n",
    "\n",
    "prop_of_risk.plot(title='Proportion of Risk of Style Factors')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "*Other questions? Reach out to the [Portfolio Analytics team](mailto:gs-marquee-analytics-support@gs.com)!*"
   ],
   "metadata": {
    "collapsed": false
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}